#ifndef _tenacitas__balance_line__test1_h_
#define _tenacitas__balance_line__test1_h_

#include <tenacitas.balance_line/balance_line.h>

#include <list>
#include <cstdint>
#include <memory>
#include <algorithm>
#include <string>
#include <iostream>


namespace tenacitas {
    /** namespace for the project */
    namespace balance_line {
        namespace test1 {

            /** a type of source */
            template <typename t_data>
            struct source {
                typedef std::shared_ptr<source> ptr;
                typedef t_data data;
                typedef std::shared_ptr<data> data_ptr;

                source( const std::string &p_name )
                    : m_name( p_name ),
                      m_list( ),
                      m_current( m_list.end( ) ) {}

                data_ptr read( ) {
                    if ( ( m_list.empty( ) ) || ( m_current == m_list.end( ) ) ) {
                        return data_ptr( );
                    }
                    data_ptr l_data = *m_current;
                    ++m_current;
                    return l_data;                    
                }

                void add( data_ptr p_data ) {
                    m_list.push_back( p_data );
                    m_current = m_list.begin( );
                }

                void add( const data & p_data ) {
                    data_ptr l_data( new data( p_data ) );
                    m_list.push_back( l_data );
                    m_current = m_list.begin( );
                }

                void sort( ) {
                    m_list.sort( data_ptr_less( ) );
                    m_current = m_list.begin( );
                }

                void print( ) {
                    std::cout << "source '" << m_name << "' contains: ";
                    
                    const_iterator l_end = m_list.end( );                    
                    for( const_iterator l_ite = m_list.begin( );
                         l_ite != l_end;
                         ++l_ite ) {
                        std::cout  << **l_ite << " ";
                    }
                    std::cout << std::endl;
                }

                const std::string & name( ) const {
                    return m_name;
                }
                

            private:
                typedef std::list<data_ptr> list;

                typedef typename list::iterator iterator;

                typedef typename list::const_iterator const_iterator;                

                struct data_ptr_less {
                    bool operator( )( data_ptr l_left, data_ptr l_right ) {
                        return ( ( *l_left ) < ( *l_right ) );
                    }
                };

                std::string m_name;
                
                list m_list;

                iterator m_current;
            };

            /** runs the test */
            void run( );

            void f0( );
        }
    }
}


#endif
